package org.zero.onlinesubject.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mysql.cj.util.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.zero.onlinesubject.common.constant.RedisConstant;
import org.zero.onlinesubject.common.vo.TaskPubVo;
import org.zero.onlinesubject.entity.*;
import org.zero.onlinesubject.mapper.*;
import org.zero.onlinesubject.service.MessageNotifyService;
import org.zero.onlinesubject.service.TaskPubService;
import org.springframework.stereotype.Service;
import org.zero.onlinesubject.utils.IDWorker;
import org.zero.onlinesubject.utils.UserContextHolder;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 *
 */
@Service
public class TaskPubServiceImpl extends ServiceImpl<TaskPubMapper, TaskPub>
    implements TaskPubService{
    @Resource
    private TaskTypeMapper taskTypeMapper;

    @Resource
    private MessageNotifyService messageNotifyService;

    @Resource
    private TaskDetailsMapper taskDetailsMapper;

    @Resource
    private TaskConfRecordsMapper taskConfRecordsMapper;

    @Resource
    private TaskPubMapper taskPubMapper;

    @Resource
    private ClassInfoMapper classInfoMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private ThreadService threadService;

    @Override
    public List<TaskType> getTaskTypes() {
        String body = stringRedisTemplate.opsForValue().get(RedisConstant.TASK_TYPE_PREFIX);
        if(!StringUtils.isNullOrEmpty(body)){
            return JSON.parseObject(body, new TypeReference<List<TaskType>>() {});
        }

        List<TaskType> taskTypes = taskTypeMapper.selectList(null);
        stringRedisTemplate.opsForValue().set(RedisConstant.TASK_TYPE_PREFIX,JSON.toJSONString(taskTypes),2,TimeUnit.HOURS);;
        return taskTypes;
    }

    @Override
    public Boolean saveTask(TaskDetails taskDetails) {
        return taskDetailsMapper.insert(taskDetails) != 0;
    }

    @Transactional
    @Override
    public Boolean publishTask(TaskPub taskPub) {
        String publisherid = taskPub.getPublisherid();
        User user = UserContextHolder.get();
        if(!Objects.equals(user.getUserid(), publisherid)){
            throw new RuntimeException("发布任务的用户id和当前登录用户的id不一致");
        }
        if(StringUtils.isNullOrEmpty(taskPub.getAssignto())){
            throw new RuntimeException("没有选择任务的发布对象");
        }
        String cid = taskPub.getAssignto();
        int row = taskPubMapper.insert(taskPub);
        if(row == 0) return false;
        List<String> uids = classInfoMapper.getJoinUser(cid);
        uids.remove(user.getUserid());
        List<MessageNotify> messages = new ArrayList<>();
        uids.stream().forEach(u->{
            MessageNotify message = new MessageNotify();
            message.setSenderid(publisherid);
            message.setRecepientid(u);
            message.setIsread(false);
            message.setNotifytitle(taskPub.getDescription());
            message.setNotifydate(LocalDateTime.now());
            message.setTypecode(taskPub.getTasktype());
            message.setLevel(taskPub.getLeveltype());
            message.setTaskid(taskPub.getTaskid());
            messages.add(message);
        });
        Boolean flag = messageNotifyService.saveBatch(messages);
        threadService.removeMsgCache(uids,stringRedisTemplate);
        return flag;
    }

    @Override
    public TaskPubVo getTaskInfo(String taskId) {
        String json = stringRedisTemplate.opsForValue().get(RedisConstant.TASK_IFNO_PREFIX + taskId);
        if(!StringUtils.isNullOrEmpty(json)){
            return JSON.parseObject(json, TaskPubVo.class);
        }

        List<TaskType> taskTypes = null;
        String json2 = stringRedisTemplate.opsForValue().get(RedisConstant.TASK_TYPE_PREFIX);
        if(!StringUtils.isNullOrEmpty(json2)){
            taskTypes = JSON.parseObject(json2,new TypeReference<List<TaskType>>(){});
        }else{
            taskTypes = getTaskTypes();
        }
        Map<String, String> map = taskTypes.stream().collect(Collectors.toMap(TaskType::getTypecode, TaskType::getName));

        TaskPubVo vo = taskPubMapper.getTaskInfo(taskId);
        vo.setTypename(map.get(vo.getTypename()));
        stringRedisTemplate.opsForValue().set(RedisConstant.TASK_IFNO_PREFIX + taskId,JSON.toJSONString(vo),10, TimeUnit.MINUTES);
        return vo;
    }
}




